﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace Jailu.AutoUpdater
{
    public partial class frmMain : Form
    {
        private string serverUrl = "http://localhost/AutoUpdater/AutoUpdate.xml";

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            this.InitAutoUpdater();

            this.ChangeFileDownloadingStatusAction = this.ChangeFileDownloadingStatus;
            this.ChangeProgressBarValueAction = this.ChangeProgressBarValue;

            if (this.AutoUpdater.HasNewVersion)
            {
                if (MessageBox.Show("New version is available.\r\nAre you going to download the new version", "New version is available", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    Thread thread = new Thread(this.DownloadNewVersion);
                    thread.Start();
                };
            }
            else
            {
                MessageBox.Show("No new version.");
            }
        }

        private void InitAutoUpdater()
        {
            this.AutoUpdater = new AutoUpdater(serverUrl);

            this.AutoUpdater.QueueStarted += new Action<QueueStartedEventArgs>(AutoUpdater_QueueStarted);
            this.AutoUpdater.QueueFinished += new Action<QueueFinishedEventArgs>(AutoUpdater_QueueFinished);
            this.AutoUpdater.FileStarted += new Action<FileStartedEventArgs>(AutoUpdater_FileStarted);
            this.AutoUpdater.FileFinished += new Action<FileFinishedEventArgs>(AutoUpdater_FileFinished);
            this.AutoUpdater.FileProgressChanged += new Action<FileProgressChangedEventArgs>(AutoUpdater_FileProgressChanged);
            this.AutoUpdater.NewVersionInstallationStarted += new Action<NewVersionInstallationStartedEventArgs>(AutoUpdater_NewVersionInstallationStarted);
            this.AutoUpdater.NewVersionInstallationFinished += new Action<NewVersionInstallationFinishedEventArgs>(AutoUpdater_NewVersionInstallationFinished);
        }

        private AutoUpdater AutoUpdater { get; set; }

        private void DownloadNewVersion()
        {
            this.AutoUpdater.Update();
        }

        #region Actions

        Action<ProgressBar, int> ChangeProgressBarValueAction;
        private void ChangeProgressBarValue(ProgressBar bar, int value)
        {
            bar.Value = value;
        }

        Action<string> ChangeFileDownloadingStatusAction;
        private void ChangeFileDownloadingStatus(string status)
        {
            lblFileDownloadingStatus.Text = status;
        }

        #endregion

        #region AutoUpdater Events

        void AutoUpdater_FileProgressChanged(FileProgressChangedEventArgs args)
        {
            this.Invoke(
                this.ChangeProgressBarValueAction,
                pgbFile,
                Convert.ToInt32((Convert.ToDouble(args.DownloadedSize) / Convert.ToDouble(args.File.Size)) * pgbFile.Step)
            );

            this.Invoke(
                this.ChangeProgressBarValueAction,
                pgbTotal,
                Convert.ToInt32((Convert.ToDouble((this.DownloadedFiles.Sum(item => item.Size) + args.DownloadedSize)) / Convert.ToDouble(this.TotalSize)) * pgbTotal.Step)
            );
        }

        void AutoUpdater_FileFinished(FileFinishedEventArgs args)
        {
            this.DownloadedFiles.Add(args.File);
        }

        void AutoUpdater_FileStarted(FileStartedEventArgs args)
        {
            this.Invoke(this.ChangeFileDownloadingStatusAction, string.Format("Downloading: {0}/{1}({2} bytes)", args.File.Path, args.File.Name, args.File.Size));
            this.Invoke(this.ChangeProgressBarValueAction, pgbFile, 0);
        }

        void AutoUpdater_QueueFinished(QueueFinishedEventArgs args)
        {
            this.Invoke(this.ChangeProgressBarValueAction, pgbTotal, pgbTotal.Step);
        }

        long TotalSize { get; set; }
        List<File> DownloadedFiles { get; set; }
        void AutoUpdater_QueueStarted(QueueStartedEventArgs args)
        {
            this.TotalSize = args.TotalSize;
            this.DownloadedFiles = new List<File>();
        }

        void AutoUpdater_NewVersionInstallationFinished(NewVersionInstallationFinishedEventArgs obj)
        {
            this.Invoke(this.ChangeFileDownloadingStatusAction, "New version installed.");
        }

        void AutoUpdater_NewVersionInstallationStarted(NewVersionInstallationStartedEventArgs obj)
        {
            this.Invoke(this.ChangeFileDownloadingStatusAction, "New version installing...");
        }

        #endregion
    }
}
